
#什么是可迭代对象，什么是迭代器？
#他们的语法规则是什么？怎么实现的？

# 1.创建一个迭代器
book_list = ['第一章', '第二章', '第三章']
it = iter(book_list)
#2.获取下一个元素
page1 = next(it)
print(page1)
page2 = next(it)
print(page2)
page3 = next(it)
print(page3)
#3.处理迭代结束情况
try:
    page4 = next(it)
    print(page4)
except StopIteration:
    print('已阅读完所以章节')

#现在看来迭代器就像是一个翻页器，自动按顺序翻找下一页
"""
    迭代器协议：必须有两个魔术方法
        __iter__():返回迭代器自身
        __next__():返回下一个元素或处理StopIteration
"""
#由协议可猜出，在上面调用iter(),next()方法时会调用对于的魔术方法，这就使触发调用的规范

# it = iter(book_list) 
#等同于
it = book_list.__iter__()

# page1 = next(it), 等同于
page1 = it.__next__()

#接下来，简单实现一个迭代器
class SimpleCounter:
    """简单计数器"""
    def __init__(self, current, end):
        self.current = current
        self.end = end
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.current > self.end:
            raise StopIteration
        else:
            current_value = self.current
            self.current += 1
            return current_value
#对于for loop:为什么可以把迭代器作为一个可迭代对象进行迭代？
#首先了解一下for loop的工作机制：
"""
    for循环需要一个可迭代对象(iterable)来进行迭代操作, 当遍历一个对象时,python解释器会按以下步骤进行：
        调用对象的 __iter__ 方法，获取一个迭代器（iterator）。
        不断调用迭代器的 __next__ 方法，获取下一个元素，直到抛出 StopIteration 异常，此时循环结束。
"""
#显然，这里的counter是一个迭代器，我们希望迭代器也可被迭代，那么就是作为一个iterable
#怎么实现呢？ 当然是通过魔术__iter__()进行实现，它实现了counter既可作为一个迭代器，也可作为一个iterable
#iterable再通过iterator进行next

counter = SimpleCounter(1, 3)
for it in counter:
    print(it)
#第二次进行for loop没有进行打印，显然是未进行迭代，SimpleCounter既作为iterable又作为iterator，再迭代到末尾时
#进行一下次迭代，返回的仍是上次迭代的位置，下面的代码给出了解释和解决方案
for it in counter:
    print('迭代中')
    print(it)

#那么接下来，让我仔细分辨一下iterable与iterator
"""
本质区别:
    可迭代对象：能够被迭代的对象（可以用 for 循环遍历）

    迭代器：实际执行迭代操作的对象（真正产生值的对象）
"""

class Countdown:
    def __init__(self, start):
        self.start = start


    def __iter__(self):
        return CountdownIterator(self.start) #每次返回一个新的迭代器
    
#真正的迭代器
class CountdownIterator:
    def __init__(self, count):
        self.count = count
    
    def __iter__(self):
        return self

    def __next__(self):
        if self.count <= 0:
            raise StopIteration
        else:
            val = self.count
            self.count -= 1
            return val

cd = Countdown(3)  # 可迭代对象
for num in cd:     # 首次迭代
    print(num, end=' ')    # 3, 2, 1
print() 
for num in cd:     # 可以重新迭代
    print(num, end=' ')     # 再次输出 3, 2, 1
print() 

"""
    可迭代对象：数据的生产者（__iter__）

    迭代器：数据的消费者（__next__）

    转换关系：iter(iterable) → iterator

    设计模式：遵循迭代器模式（Iterator Pattern）

    Python特色：通过协议实现而非强制接口
"""